package com.zqr.thread;

import com.zqr.utils.Utils;
import lombok.extern.slf4j.Slf4j;

/**
 * 包含了join的案例及三个线程通过join的方式控制运行顺序的作业（0926作业）
 */
@Slf4j
public class ThreadJoinDemo {
    public static void main(String[] args) throws InterruptedException {
//        joinTest();
        threeThreadJoinTest();
    }

    /**
     * 老师的join案例，在主线程里调用子线程的join方法，等待子线程执行完毕后主线程才恢复执行
     * @throws InterruptedException
     */
    private static void joinTest() throws InterruptedException {
        log.info("{} thread is running ....", Thread.currentThread().getName());
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                log.info("{} thread is running ......", Thread.currentThread().getName());
                Utils.sleepIgnoreExp(500);
            }
        }, "t1");
        thread.start();
        log.info("{} thread call {}'s join", Thread.currentThread().getName(), thread.getName());
        thread.join();
        log.info("{} thread continue , {} thread before join state:{}", Thread.currentThread().getName(), thread.getName(), thread.getState());
        Utils.sleepIgnoreExp(1000);
        log.info("{} thread finished", Thread.currentThread().getName());
    }

    /**
     * 作业：测试三个线程相互等待
     * 实现先运行t2，再运行t1，再运行main？
     */
    private static void threeThreadJoinTest() throws InterruptedException {
        log.info("{} thread is running ...", Thread.currentThread().getName());  //主线程正在运行

        Thread t2 = new Thread(new JoinTestRunnable(), "t2");

        Thread t1 = new Thread(new JoinTestRunnable(t2), "t1");

        t1.start();
        t2.start();

        log.info("{} thread call {}'s join", Thread.currentThread().getName(), t1.getName());
        t1.join();

        log.info("{} thread continue, {} thread state:{}, {} thread state:{}",
                Thread.currentThread().getName(), t1.getName(), t1.getState(), t2.getName(), t2.getState());
        Utils.sleepIgnoreExp(1000);
        log.info("{} thread terminate ...", Thread.currentThread().getName());
    }

    /**
     * 作业：测试三个线程相互等待    (有问题写法，main和t1互相等待，死锁）
     */
    private static void threeThreadJoinTest_Deadlock() throws InterruptedException {
        log.info("{} thread is running ...", Thread.currentThread().getName());  //主线程正在运行

        Thread t1 = new Thread(new JoinTestRunnable(Thread.currentThread()), "t1");

        Thread t2 = new Thread(new JoinTestRunnable(t1), "t2");

        t1.start();
        t2.start();
        log.info("{} thread call {}'s join", Thread.currentThread().getName(), t1.getName());
        t1.join();
        log.info("{} thread continue, {} thread state:{}, {} thread state:{}",
                Thread.currentThread().getName(), t1, t1.getState(), t2, t2.getState());
        Utils.sleepIgnoreExp(1000);
        log.info("{} thread terminate ...", Thread.currentThread().getName());
    }

    static class JoinTestRunnable implements Runnable{
        private Thread beforeThread;

        public JoinTestRunnable(Thread beforeThread) {
            this.beforeThread = beforeThread;
        }

        public JoinTestRunnable() {
        }

        @Override
        public void run() {
            if (beforeThread != null){
                log.info("{} thread call {}'s join", Thread.currentThread().getName(), beforeThread.getName());
                try {
                    beforeThread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            for (int i = 0; i < 5; i++) {
                log.info("{} thread is running ...", Thread.currentThread().getName());
                Utils.sleepIgnoreExp(500);
            }
        }
    }


}
